#ifndef PREDICATES_H
#define PREDICATES_H
#include "../abc_archive.h"
#include "path_utils.h"
#include <memory>
#include <vector>
namespace abc_query
{
    class Predicate : public std::enable_shared_from_this<Predicate>
    {
    public:
        virtual ~Predicate() = default;

        virtual bool testNode(const abc::AbcNodePtr &node) const = 0;
        virtual bool testFunction(const abc::AbcFunctionPtr &func) const = 0;

        std::shared_ptr<Predicate> And(const std::shared_ptr<Predicate> &other) const;
        std::shared_ptr<Predicate> Or(const std::shared_ptr<Predicate> &other) const;
        std::shared_ptr<Predicate> Not() const;

    protected:
        // 启用shared_from_this
        Predicate() = default;
        Predicate(const Predicate &) = default;
        Predicate &operator=(const Predicate &) = default;
    };

    // 节点类型谓词
    class NodeTypePredicate : public Predicate
    {
    public:
        explicit NodeTypePredicate(abc::AbcNodeType type);
        bool testNode(const abc::AbcNodePtr &node) const override;
        bool testFunction(const abc::AbcFunctionPtr &func) const override;

    private:
        abc::AbcNodeType type_;
    };

    // 模块谓词
    class ModulePredicate : public Predicate
    {
    public:
        explicit ModulePredicate(const std::string &module);
        bool testNode(const abc::AbcNodePtr &node) const override;
        bool testFunction(const abc::AbcFunctionPtr &func) const override;

    private:
        std::string module_;
    };

    // Package谓词
    class PackagePredicate : public Predicate
    {
    public:
        explicit PackagePredicate(const std::string &pkg);
        bool testNode(const abc::AbcNodePtr &node) const override;
        bool testFunction(const abc::AbcFunctionPtr &func) const override;

    private:
        std::string pkg_;
    };

    // 函数名谓词
    class FunctionNamePredicate : public Predicate
    {
    public:
        explicit FunctionNamePredicate(const std::string &pattern);
        bool testNode(const abc::AbcNodePtr &node) const override;
        bool testFunction(const abc::AbcFunctionPtr &func) const override;

    private:
        std::string pattern_;
    };

    class AndPredicate : public Predicate
    {
    public:
        AndPredicate(std::shared_ptr<const Predicate> left, std::shared_ptr<const Predicate> right);
        bool testNode(const abc::AbcNodePtr &node) const override;
        bool testFunction(const abc::AbcFunctionPtr &func) const override;

    private:
        std::shared_ptr<const Predicate> left_;
        std::shared_ptr<const Predicate> right_;
    };

    class OrPredicate : public Predicate
    {
    public:
        OrPredicate(std::shared_ptr<const Predicate> left, std::shared_ptr<const Predicate> right);
        bool testNode(const abc::AbcNodePtr &node) const override;
        bool testFunction(const abc::AbcFunctionPtr &func) const override;

    private:
        std::shared_ptr<const Predicate> left_;
        std::shared_ptr<const Predicate> right_;
    };

    class NotPredicate : public Predicate
    {
    public:
        explicit NotPredicate(std::shared_ptr<const Predicate> pred);
        bool testNode(const abc::AbcNodePtr &node) const override;
        bool testFunction(const abc::AbcFunctionPtr &func) const override;

    private:
        std::shared_ptr<const Predicate> predicate_;
    };

}

#endif